home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / clipper / grump14.zip / README.DOC < prev    next >
Text File  |  1988-12-03  |  74KB  |  1,814 lines

  1.               █▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀█
  2.              ▒█                                               █
  3.             ░▒█         GRUMPFISH LIBRARY VERSION 1.4         █
  4.             ░▒█   Creative Tools for the Clipper Programmer   █
  5.             ░▒█          Copyright 1988 by Greg Lief          █
  6.             ░▒█           CompuServe ID 72460,1760            █
  7.             ░▒█                Serial No. 0001                █
  8.             ░▒█                                               █
  9.             ░▒█▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█
  10.             ░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  11.             ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  12.  
  13.  
  14.     Greetings, Clipper programmer!  The Grumpfish Library contains a number
  15.     of high quality, extremely useful pop-up desktop utilities and other
  16.     functions that you can integrate into your Clipper programs with 
  17.     an absolute minimum of effort.
  18.  
  19.     The pop-up applications include a full-featured calculator, phone
  20.     number/address database, notepad/word processor, calendar, fully user-
  21.     definable context-specific help screens, Mastermind game, and puzzle.
  22.     The functions include automatic generation of vertical and
  23.     horizontal bounce-bar menus, user-defined queries (filters),
  24.     exploding, shrinking, pop-up and drop-down boxes, a global
  25.     replacement capability that simulates the flexibility of the dBASE
  26.     dot prompt, and plenty of other useful things.  Also included is a
  27.     musical library of various themes that you can stick into your
  28.     program to amuse yourself and/or annoy the end user.
  29.  
  30.     In general, to use a Grumpfish application or function, you merely use
  31.     the command to call the function in your source code, then link your
  32.     application with GRUMP.LIB.  Only the required code will be included
  33.     from the library file, thus eliminating unnecessary overhead.
  34.  
  35.     *** IMPORTANT: The Grumpfish Library is written entirely in Clipper
  36.     using the Summer '87 version.  If you are using an earlier version of
  37.     Clipper, some of the Grumpfish functions may not link properly because
  38.     they utilize some of the new Clipper functions.  However, if you are a
  39.     registered Clipper owner and have not yet updated to Summer '87, what
  40.     are you waiting for?  The speed advantages alone are worth it!
  41.  
  42.   
  43. LICENSE INFORMATION
  44.  
  45.     The Grumpfish Library is protected by U.S. Copyright law, and is
  46.     NOT "shareware" or public domain software.  You are hereby granted
  47.     a limited license to make an evaluation copy for trial use on a
  48.     private, non-commercial basis for the express purpose of
  49.     determining whether the Grumpfish Library is suitable for your
  50.     programming needs.
  51.     
  52.     At the end of this trial period, you should either register your copy
  53.     or discontinue using the Grumpfish Library in your Clipper programs.
  54.  
  55.     Registration will entitle you to a comprehensive run-time royalty-
  56.     free license arrangement, at which time you can freely incorporate 
  57.     any or all Grumpfish Library functions in your commercial programs.
  58.     
  59.     You are encouraged to freely distribute copies of the entire Grumpfish
  60.     Library package, which consists of the archive file GRUMP14.ARC.
  61.     Please do not distribute the files in their de-archived form.
  62.  
  63.  
  64. REGISTRATION
  65.  
  66. 1.  BENEFITS
  67.  
  68.     If you find the Grumpfish Library useful in your Clipper programming
  69.     endeavors, you must register your copy.  There are two levels of
  70.     registration, Landlubber and Captain, which entitle you to the
  71.     following benefits:
  72.  
  73.                                LANDLUBBER ($30)
  74.  
  75.     1.  The most current version of the Grumpfish Library delivered to
  76.         your home by the United States Postal Service, with your
  77.         personal registration number on this screen.
  78.  
  79.     2.  Run-time royalty-free license.  In other words, you will be free to
  80.         integrate any or all functions of the Grumpfish Library into your
  81.         own Clipper applications without having to pay any royalty or fee
  82.         for doing so.  You may also distribute or market any such
  83.         applications royalty-free.
  84.  
  85.     3.  Notification of future versions of the Grumpfish Library.  I have
  86.         been averaging a new release about every six weeks for the last
  87.     four months, and, with sufficient user feedback, expect to continue
  88.     in this vein.
  89.  
  90.                                 CAPTAIN ($60)
  91.  
  92.     All Landlubber's benefits listed above, plus
  93.  
  94.     4.  The source code for all functions and applications in the Grumpfish
  95.         Library, written entirely in Clipper (Summer '87).  The code is
  96.         well-documented, and is invaluable as a learning tool for beginning
  97.         and intermediate programmers.  More advanced programmers will be
  98.         able to customize the applications and functions as desired.
  99.  
  100.     5.  Free telephone support (beginning in January 1989 -- see below)
  101.      
  102.         Please bear in mind, however, that item 4) does NOT entitle you
  103.         to distribute or sell Grumpfish functions!  This constitutes
  104.         a violation of the U.S. copyright on this program.
  105.  
  106.     Grumpfish Library features can be customized to suit your company's
  107.     specific needs.  Please contact me for more information.
  108.  
  109.     Special user group registrations or site licenses are available.
  110.     Please write if you are interested.
  111.  
  112. 2.  HOW TO REGISTER
  113.  
  114.      a.  At the DOS prompt, type "COPY ORDER PRN" to print the registration
  115.          form.  This form is a self-contained mailer, so you won't
  116.          have to bother with an envelope.
  117.  
  118.      b.  Mail the completed form with your check or money order for $30 or 
  119.          $60 to:
  120.  
  121.                              Charles G. Lief
  122.                              P. O. Box 17761
  123.                              Salem, Oregon 97305
  124.  
  125. 3.  SUPPORT
  126.  
  127.     At the moment, I am not offering telephone support, but I expect
  128.     to begin doing so for Level B registered users in January 1989.  
  129.     In the meantime, however, I will be happy to answer all corres-
  130.     pondence sent to me via either U.S. Mail or CompuServe (ID 72460,
  131.     1760).  You DO NOT have to be a registered owner to contact me; 
  132.     if you have a particular problem or have stumbled across some 
  133.     magnetic critter that snuck past me, I want to hear from you!
  134.     
  135.  
  136. USER GROUPS/SHAREWARE DISTRIBUTORS
  137.  
  138.      PC User Groups are welcome to add the Grumpfish Library to their
  139.      libraries under the following conditions:
  140.  
  141.         1) it must be completely unmodified;
  142.  
  143.         2) a diskette/copying fee of $5 or less is charged; and
  144.  
  145.         3) this documentation file MUST be included.
  146.  
  147.      I would appreciate notification that you have added Grumpfish
  148.      Library to your library.
  149.  
  150.      If you have received the Grumpfish Library through either a user
  151.      group or a shareware distributor, please remember that the
  152.      diskette fee you paid DOES NOT constitute licensing the software,
  153.      and you are still obligated to register if you decide to use
  154.      Grumpfish Library features in your Clipper programming endeavors.
  155.  
  156.  
  157. STARTING OUT
  158.  
  159.      For convenience's sake, copy GRUMP.LIB to the same subdirectory where
  160.      CLIPPER.LIB and EXTEND.LIB are located.
  161.  
  162.  
  163. USING THE GRUMPFISH LIBRARY
  164.  
  165.      To use any of the Grumpfish applications or functions, you must first
  166.      link in the Grumpfish library (GRUMP.LIB).  In addition, you will need
  167.      to link in Clipper's Extend library (EXTEND.LIB), because nearly
  168.      all of the Grumpfish Library functions call functions in this
  169.      library.
  170.  
  171.      The following are examples of what you would enter at the DOS prompt
  172.      for the three most commonly used linkers (<yourfile> represents the
  173.      name of your main .obj file):
  174.  
  175.      For PLINK86 linker:   PLINK86 FI <yourfile> LIB GRUMP,EXTEND,CLIPPER
  176.  
  177.      For the DOS linker:   LINK <yourfile>,,,GRUMP + EXTEND + CLIPPER
  178.  
  179.      For Borland's TLINK:  TLINK <yourfile>,,,GRUMP EXTEND CLIPPER
  180.  
  181.      Note that if your libraries are not located in the same subdirectory
  182.      where linking is being performed, you will have to add the drive
  183.      and/or path to prevent the linker from choking!
  184.  
  185.  
  186. TABLE OF CONTENTS
  187.  
  188.      POPCALC....... Pop-up calculator
  189.      POPPHONE...... Pop-up phone directory
  190.      POPDATE....... Pop-up calendar
  191.      POPSTOP....... Pop-up stopwatch
  192.      POPMM......... Pop-up Mastermind game
  193.      POPPUZ........ Pop-up logic puzzle
  194.      HELP/HELPDEV.. Pop-up user-defined help screens
  195.      POPNOTE....... Pop-up notepad
  196.      YES_NO()...... Display yes/no question and wait for response
  197.      ERR_MSG()..... Display error message and wait for keypress
  198.      CENTER()...... Centers a character string on specified row
  199.      WAITON()...... Display visual feedback for tedious processes
  200.      WAITOFF()..... Restore screen after using WAITON()
  201.      EXBOX()....... Exploding box
  202.      SHRBOX()...... Shrinking box -- opposite of EXBOX()
  203.      POPBOX()...... Pop-up box
  204.      DROPBOX()..... Drop-down box
  205.      SETFILT()..... Create pseudo-SQL query of any database file
  206.      BATCHREP().... Simulate dBASE dot prompt global replacement
  207.      MEMEDIT()..... Edit a memo field
  208.      MENUH()....... Display horizontal bounce-bar menu
  209.      MENUV()....... Display vertical bounce-bar menu
  210.      NET_USE()..... Opens files in multi-user environments
  211.      REC_LOCK().... Attempts to lock a record
  212.      FILELOCK().... Attempts to lock a file
  213.      ADD_REC()..... Attempts to APPEND BLANK to current file
  214.      HELPBROW().... Interactive help screen for data validation
  215.      PRINTOK()..... Tests for printer status and informs user if problem
  216.      DATEST()...... Returns blank spaces for empty dates 
  217.      ISSTATE()..... For validating entry of state abbreviations
  218.      SPREAD()...... Display character string from the middle out
  219.      TTY()......... Move a character string continuously across the screen 
  220.      PASS_CHK().... Get password from user
  221.      RAND()........ Returns a random number in the specified range
  222.      TIMEWORD().... Returns word describing the time of day (morning, etc.)
  223.      GL_VER()...... Returns version number of Grumpfish Library
  224.      BEATIT........ Plays the opening riff from "Beat It"
  225.      BORN2RUN...... Plays a verse and chorus from "Born To Run"
  226.      CHARGE........ Plays the venerable "Charge!" theme
  227.      HATDANCE...... Plays the Mexican Hat Dance
  228.      IPANEMA....... Plays the opening bars of "The Girl From Ipanema"
  229.      JEOPARDY...... Plays the theme from Final Jeopardy
  230.      DECKHALL...... Plays "Deck The Halls"
  231.      JINGLE........ Plays "Jingle Bells"
  232.      RUDOLPH....... Plays "Rudolph The Red-Nosed Reindeer"
  233.  
  234.  
  235. POP-UP APPLICATIONS
  236.  
  237. 1.  CALCULATOR
  238.  
  239. a.  Description and Usage:
  240.  
  241.     This is a useful calculator that includes all the basic operators:
  242.     addition (+), subtraction (-), multiplication (*), and division (/).
  243.     But it also has some other goodies, including exponentation (^), a
  244.     paste function and a full-featured memory.  Plus, whenever you press an
  245.     operator ('+', '-', '*', '/', or '^'), the previous number is shown
  246.     above the display window.  This is handy for when you are processing a
  247.     list of numbers and forget where you were.
  248.  
  249.     Active Keys:
  250.  
  251.     '+' -- addition                        '-' -- subtraction
  252.  
  253.     '*' -- multiplication                  '/' -- division
  254.  
  255.     '^' -- exponentation                   'C' -- clear current number
  256.  
  257.     'E' -- clear entry (does not clear previously entered number in
  258.             pending operation)
  259.  
  260.     '=' or Enter -- process operation       Esc -- exit Calculator
  261.  
  262. b.  Memory Functions:
  263.  
  264.     To access memory functions, press "M", then one of the flashing
  265.     function keys.  The function keys are:
  266.  
  267.     'R' -- recall number stored in memory
  268.  
  269.     'C' -- clear memory (reset to zero)
  270.  
  271.     '+' -- add current number to number stored in memory
  272.  
  273.     '-' -- subtract current number from number stored in memory
  274.  
  275.     '*' -- multiply number stored in memory by current number
  276.  
  277.     '/' -- divide number stored in memory by current number
  278.  
  279.     The maximum value that can be stored in the calculator is
  280.     99,999,999,999.9999.
  281.  
  282.     The paste function enables you to paste the current calculator value
  283.     into a pending READ by pressing a designated hot key (Ctrl-P is
  284.     suggested).  PASTE CAVEAT: erratic results may occur if the number
  285.     of decimal places in the number to be pasted is larger than the 
  286.     number of decimals in the memory variable or field.  For example,
  287.     suppose that you have just used the calculator to derive the result
  288.     75.2877.  You wish to paste this number into a memory variable
  289.     mTOTAL, which you are GETting with a picture template of '###.##'.
  290.     The probability is strong that this number will be stored
  291.     on-screen as 75.29 (although internally it will remain 75.2877).
  292.  
  293. c.  Using the Calculator in your Clipper application:
  294.  
  295.     There are two ways that you can make use of the calculator.  The first
  296.     method is to use the SET KEY command to establish a "hot-key" so that
  297.     the user can pop up the calculator anywhere within the program. The
  298.     following lines added at the top of your program configures the F6 key
  299.     to serve as the hot key for the pop-up calculator and Ctrl-P as the hot
  300.     key for the paste function:
  301.  
  302.            EXTERNAL popcalc   && define external symbol for linker
  303.            PUBLIC paste_no    && holds current calculator value for pasting
  304.            calckey = -5       && hot key will be function key F6
  305.            SET KEY calckey TO popcalc
  306.            SET KEY 16 to paste  && Ctrl-P (optional)
  307.  
  308.     If you want to use different keys as hot keys, please refer to your
  309.     Clipper manual for a list of INKEY() values.
  310.  
  311.     The second method is to call the calculator directly.  The following is
  312.     a sample menu including the calculator as a menu option:
  313.  
  314.            PUBLIC paste_no
  315.            SET KEY 16 TO paste
  316.                  |
  317.                  |
  318.                  |
  319.            @ 05,05 PROMPT "Data Entry"
  320.            @ 06,05 PROMPT "Reports"
  321.            @ 07,05 PROMPT "Calculator"
  322.            @ 08,05 PROMPT "Exit to Operating System"
  323.            MENU TO selection
  324.  
  325.            DO CASE
  326.               CASE selection = 1
  327.                  DO dataentry
  328.               CASE selection = 2
  329.                  DO reports
  330.               CASE selection = 3
  331.                  DO popcalc
  332.               CASE selection = 4
  333.                  QUIT
  334.            ENDCASE
  335.  
  336.     Although the second method may appeal to some of you, I highly
  337.     recommend using SET KEY so as to permit the user access to the
  338.     calculator from anywhere within the program.
  339.  
  340.  
  341. 2.  PHONE DIRECTORY
  342.  
  343. a.  Description:
  344.  
  345.     This application allows the user to maintain a phone database with
  346.     names, addresses, and phone numbers of business and personal contacts.
  347.     It utilizes two files, PHONE.DBF and PHONE.NTX.  You do not need to
  348.     create these files; the application automatically generates them if it
  349.     cannot find them in the specified subdirectory.
  350.  
  351.     The user interface is a browse-style window.  The user can view, add,
  352.     edit, and delete records from the phone database.  You can instruct the
  353.     application to search a specific subdirectory for the database file by
  354.     initializing a memory variable named 'phonedir' with the value of the
  355.     desired directory (example: "C:\PHONE").  If 'phonedir' is not defined
  356.     in your program, the current directory will be used.
  357.  
  358.     Active Keys:
  359.  
  360.     A -- add a record to the database
  361.  
  362.     E -- edit highlighted record
  363.  
  364.     D -- delete highlighted record
  365.  
  366.     Arrow keys -- scroll through the database
  367.  
  368.     Esc -- exit the phone directory
  369.  
  370.     F2 -- view/edit address information for the highlighted record
  371.  
  372.     Pressing F2 allows the user to view and/or edit address information for
  373.     the highlighted person.  A box containing that information will appear
  374.     in the middle of the screen.  The user can enter information in these
  375.     fields as desired.  They can then press Ctrl-W to save their edits, or
  376.     Esc to exit without saving.  Either way, they will be returned to the
  377.     browse window.
  378.  
  379. b.  Using the Phone Directory in your Clipper applications:
  380.  
  381.     As with the calculator, there are two methods to choose from.  The
  382.     first is to use SET KEY to establish a hot-key so that the user can pop
  383.     up the phone directory anywhere within the program.  The following
  384.     lines added at the top of your program configures the F7 key to serve
  385.     as the hot key, and instructs the program to look for the phone
  386.     database in the subdirectory "C:\PHONE":
  387.  
  388.            EXTERNAL popphone       && define external symbol for linker
  389.            phonekey = -6           && hot key will be function key F7
  390.            phonedir = 'C:\PHONE'   && search directory for phone.dbf
  391.            SET KEY phonekey TO popphone
  392.  
  393.     If you want to use a different hot key for the phone directory, please
  394.     refer to your Clipper manual for a list of INKEY() values.
  395.  
  396.     The second method is to call the phone directory directly.  Refer to
  397.     the Calculator discussion for a sample menu.  Once again, I highly
  398.     recommend using the SET KEY method.
  399.  
  400.  
  401. 3.  CALENDAR
  402.  
  403. a.  Description and Usage:
  404.  
  405.     This is a pop-up calendar that displays the current month and the first
  406.     two weeks of the next month.  The current day will blink.  Press any
  407.     key to exit the calendar.
  408.  
  409. b.  Using the Calendar in your Clipper applications:
  410.  
  411.     As with the other applications, there are two ways to utilize the
  412.     calendar. The first is to use SET KEY to establish a hot-key so that
  413.     the user can pop up the calendar anywhere within the program.  The
  414.     following lines added at the top of your program configures the F8 key
  415.     to serve as the hot key for the calendar:
  416.  
  417.            EXTERNAL popdate   && define external symbol for linker
  418.            datekey = -7       && hot key will be function key F8
  419.            SET KEY datekey TO popdate
  420.  
  421.     If you want to use a different hot key for the calendar, please refer
  422.     to your Clipper manual for a list of INKEY() values.
  423.  
  424.     The second method is to call the calendar directly.  Refer to the
  425.     Calculator discussion for a sample menu.  However, I recommend using
  426.     SET KEY.
  427.  
  428.  
  429. 4.  STOPWATCH
  430.  
  431. a.  Description and Usage:
  432.  
  433.     Here is a pop-up stop watch that logs minutes, seconds, and hundredths
  434.     of seconds.  You never know when you might need one.  Operation is
  435.     simple: press the space bar to start and stop.  Press Esc to quit.
  436.  
  437. b.  Using the Stopwatch in your Clipper applications:
  438.  
  439.     As with the other applications, there are two ways to utilize the
  440.     stopwatch. The first (and best) is to use SET KEY to establish a hot-
  441.     key so that the user can pop up the stopwatch anywhere within the
  442.     program.  The following lines added at the top of your program
  443.     configures the F5 key to serve as the hot key for the stopwatch:
  444.  
  445.            EXTERNAL popstop   && define external symbol for linker
  446.            stopkey = -4       && hot key will be function key F5
  447.            SET KEY stopkey TO popstop
  448.  
  449.     If you want to use a different hot key for the stopwatch, please refer
  450.     to your Clipper manual for a list of INKEY() values.
  451.  
  452.     The second method is to call the stopwatch directly.  See the
  453.     Calculator section above for a sample menu.  Once again, however, I
  454.     recommend using SET KEY.
  455.  
  456.  
  457. 5.  HELP SCREENS
  458.  
  459. a.  Description and Usage
  460.  
  461.     Context-specific pop-up help screens add enormous user-friendliness to
  462.     any program.  With the Grumpfish Library, it is a breeze to create your
  463.     own fully-customized help screens.  
  464.     
  465.     There are two stages to the help screen process: development, and 
  466.     post-development (release).  The fundamental difference between the
  467.     two stages is that the help screens can only be created during 
  468.     the development stage.  
  469.     
  470.     i.  Development Stage
  471.     
  472.     To develop the help screens, add these two lines at the top of your 
  473.     program:
  474.  
  475.            EXTERNAL helpdev        && declare symbol for linker
  476.            SET KEY 28 TO helpdev   && redefine F1 key  
  477.  
  478.     Next, recompile and link your program, because the actual creation of
  479.     the help screens takes place interactively from within your program.
  480.     Then run the program.
  481.  
  482.     You may create a help screen for any wait state.  Wait state commands
  483.     include ACCEPT, INPUT, MENU TO, MEMOEDIT(), READ, and WAIT.  When you
  484.     are at a wait state where you wish to have a help screen, press F1. If
  485.     this is the first time you have called the HELP function, the program
  486.     will take a few seconds to initialize the HELP database.  Three files
  487.     will be created in the default directory: HELP.dbf, HELP.dbt, and 
  488.     HELP.ntx.  These files should not be deleted!  If you do delete them, 
  489.     any previously-created help screens will have to be recreated.
  490.  
  491.     Assuming that you have not already created a help screen for this
  492.     particular wait state, you will get a help screen with the message:
  493.  
  494.                            No help text defined...
  495.                  Press F2 to create, any other key to return
  496.  
  497.     Press F2 to create the help screen text, then type it in exactly as you
  498.     wish it to appear.  Once you are satisfied with the text, press Ctrl-W
  499.     to save it.  You will then be prompted to enter the coordinates where 
  500.     you wish the help screen box to appear, and the title for this help
  501.     screen.  The title will be centered on the top row of the box.  
  502.     
  503.     Once you have finished entering these items, you will be asked to
  504.     select a box outline from the six that will appear in the middle
  505.     of the screen.  When you select a box, a color palette containing all
  506.     of the 128 possible foreground/background combinations will be drawn
  507.     near the bottom of your screen.  You will then be prompted to enter
  508.     the desired color number for (a) the box outline, (b) the box title,
  509.     and (c) the text.  
  510.     
  511.     When you have defined your help screen, it will be painted with your
  512.     desired characteristics.  You will then be asked to confirm that you
  513.     are satisfied with its appearance.  If you aren't, it is a simple
  514.     matter to go back and change it until you ARE satisfied.  All values
  515.     that you enter will be retained, which means that you could go back
  516.     and quickly change the text color, for example, without having to 
  517.     re-enter all of the other items.
  518.     
  519.     The next time that you (or an end user) presses F1 at this point
  520.     in the program, your fully-customized help screen will appear to
  521.     guide them through the magnetic wilderness.  The cursor keys can
  522.     be used to scroll through it, or you may print the entire help
  523.     text by pressing Alt-P.
  524.     
  525.     There is also a hidden function that enables you to edit the text 
  526.     and attributes of any help screen.  Press F1 to pop up the help 
  527.     screen, then press Alt-E (for Edit).  You are then free to edit it 
  528.     as you see fit.  Press Ctrl-W to save your text edits.  You will 
  529.     then be prompted to enter the values for the various box attributes
  530.     similarly to when you created the help screen.  This function is 
  531.     "hidden" because of the strong probability that most of your programs 
  532.     will be used by other people.
  533.  
  534.     ii.  Post-Development (Release) Stage
  535.     
  536.     When you are fairly certain that all the necessary help screens 
  537.     have been created, you will probably want to 'lock' the program in 
  538.     such a manner that your users cannot run amuck creating their own
  539.     help screens.  To create such a lock, replace the two lines you  
  540.     added previously:
  541.     
  542.            EXTERNAL helpdev        && declare symbol for linker
  543.            SET KEY 28 TO helpdev   && redefine F1 key  
  544.  
  545.     with the following line:
  546.     
  547.            EXTERNAL help           && declare symbol for linker
  548.        
  549.     Then recompile and link your program.  Everything will be the same,
  550.     except that your users will be powerless to create their own help
  551.     screens.  You will also notice that the .EXE file will be smaller
  552.     by approximately 4,000 bytes.  This is because the routines for
  553.     customizing the appearance of the help screens are no longer 
  554.     necessary.  
  555.     
  556.     If you or your end users decide that creation of further help 
  557.     screens is necessary, you can always switch back to HELPDEV.
  558.     
  559.     Thanks to Bill Altman of Hampton Bays, NY for suggesting increased
  560.     flexibility with the layout and color of these help screens.
  561.  
  562.  
  563. 6.  NOTEPAD / WORD PROCESSOR
  564.  
  565. a.  Description and Usage:
  566.  
  567.     Developers and end users alike will benefit from this snazzy
  568.     pop-up notepad.  The heart of the notepad is Clipper's MEMOEDIT(),
  569.     so all of that function's basic Wordstar-type commands are available
  570.     herein (a full listing of these commands can be found in your Clipper 
  571.     manual).  However, I have added a number of useful mnemonic
  572.     commands, which are based on the following Alt-key combinations:
  573.  
  574.     Alt-A  (A)ppend a file to current file and continue
  575.     Alt-G  (G)oto line number               Alt-H  (H)elp screen
  576.     Alt-I  (I)nsert line                    Alt-K  (K)ill current line
  577.     Alt-L  page (L)ength for printing       Alt-M  change (M)argins
  578.     Alt-N  edit (N)ew file                  Alt-P  (P)rint file
  579.     Alt-Q  (Q)uit but save edits            Alt-R  search and (R)eplace
  580.     Alt-S  (S)ave file & continue           Alt-T  (T)oggle wordwrap on/off
  581.     Alt-W  (W)rite to new file              Alt-X  e(X)it without saving
  582.     Alt-Y  change director(Y)/wildcard
  583.  
  584.     EDIT WINDOW/STATUS LINE: when you enter the notepad, the edit
  585.     window takes up nearly the full screen.  There is a status line at
  586.     the bottom, which displays the name of the file being edited (sans
  587.     directory), the current line and column position of the cursor,
  588.     the left and right margins, and the status of wordwrap and insert
  589.     modes (displayed when active as "<Wrap>" and "<Ins>", respectively.)
  590.     
  591.     CURRENT DIRECTORY/WILDCARD - the notepad gives you the ability to
  592.     change the working directory and/or filemask at any time.  When 
  593.     you first enter the notepad, the current directory will be set to
  594.     the default DOS directory, and the wildcard will be set to '*.*'.
  595.     If you would like to change either the directory where the notepad
  596.     looks for files or the wildcard used (e.g., "*.TXT", "*.PRG"),
  597.     press Alt-Y and enter the new information.  You do not have to
  598.     enter slashes in front or back of the directory name UNLESS you
  599.     include a wildcard.  For example, to change the current directory
  600.     to "\GRUMP\", you need only enter "GRUMP".  However, if you want
  601.     the notepad to look for all the .PRG files in subdirectory
  602.     \GRUMP\, you must enter "\GRUMP\*.PRG".
  603.     
  604.     If you enter just the wildcard, the current directory will remain 
  605.     unchanged.  If you enter a directory name only, the wildcard will
  606.     be reset to "*.*".  If you press Enter without typing in anything,
  607.     neither the current directory nor the wildcard will be changed.
  608.  
  609.     Examples: let's assume that your application is in a subdirectory
  610.     named \WORKSTUF.  The initial current directory/wildcard will be 
  611.     set to "\WORKSTUF\*.*".  If you press Alt-Y and enter "*.PRG <CR>",
  612.     the directory/wildcard will be changed to "\WORKSTUF\*.PRG".  If
  613.     you wish to change to the \GRUMP subdirectory, press Alt-Y and 
  614.     enter "GRUMP <CR>".  The directory/wildcard will then be changed
  615.     to "\GRUMP\*.*".  Suppose you then want to look at only the .PRG
  616.     files starting with the letter P in the directory \WORKSTUF\DEVEL.
  617.     You would press Alt-Y again, and enter "\WORKSTUF\DEVEL\P*.PRG".  
  618.  
  619.     To retain the current directory and wildcard, you may declare 
  620.     PUBLIC variables CURR_DIR and WILDCARD before calling the notepad.  
  621.     This feature allows you to exit the notepad, and return later
  622.     without having to reset the directory and wildcard.  You may also
  623.     wish to initialize these variables to suit your specific needs
  624.     (see the example below).
  625.       
  626.     FILENAMES: when you press Alt-N to edit a new file or Alt-W to 
  627.     write to another file, a scrolling window will appear containing 
  628.     all files that match the current directory and wildcard mask.  
  629.     The directory and wildcard mask will be shown at the top of this
  630.     window for reference.  To select a file, move the highlight bar 
  631.     to it and press Enter.  To create a new file, select the option
  632.     'NEW FILE', then enter the filename.  Pressing Esc will abort the
  633.     file selection process.
  634.  
  635.     If you attempt to write to a file that already exists, or append 
  636.     from a file that does not exist, you will get an error message to 
  637.     that effect.  
  638.  
  639.     To retain the working filename, declare a PUBLIC variable named
  640.     NOTEFILE before calling the notepad.  This feature allows you to
  641.     edit a file, exit the notepad, and return to the notepad later to
  642.     find the same file waiting for you.  You may also wish to 
  643.     initialize this variable to the name of the default file for 
  644.     editing (the internal default is "TEMP").
  645.     
  646.     INSERT and WORDWRAP: the start-up values for these modes is on.  
  647.     They may toggled off and on at any time by pressing Insert and 
  648.     Alt-W, respectively.  The status of these modes appears at the right
  649.     side of the status line.
  650.     
  651.     MARGINS: the start-up margins are 1 and 78.  You can change these
  652.     at any time by pressing Alt-M and entering the desired values.
  653.     When you change the margins, the on-screen display will adjust to
  654.     reflect the new margins.  You may use larger values for the right
  655.     margin than would appear on the 80-column screen.  In such instances,
  656.     you should toggle wordwrap off and scroll to the right to display 
  657.     text beyond the on-screen right margin.  The current values of the
  658.     margins appears on the status line.  
  659.  
  660.     PAGE LENGTH: the start-up page length for printing is 60 lines.  You
  661.     can change this at any time by pressing Alt-L.  
  662.  
  663.     SEARCH AND REPLACE: you can search and replace for all or for only
  664.     a specific number of occurrences of a character string.  When you
  665.     press Alt-R, you will be prompted first to enter the search string,
  666.     then the replacement string.  You will then be asked if you want to
  667.     replace all occurrences of the search string.  If you answer 'N',
  668.     you will be prompted to enter the number of occurrences to replace.
  669.     Please note that the search begins at the top of the file and 
  670.     continues either to the end of the file or until the specified 
  671.     number of occurrences have been replaced.
  672.  
  673.     PRINTING: you may print the current file at any time by pressing 
  674.     Alt-P.  Printing may be aborted at any time by pressing Esc.  The 
  675.     format of the printed page is determined by the current settings 
  676.     of the margins and page length.  
  677.     
  678.     You may send a set-up string to the printer by defining a character
  679.     variable named SETUP_STR before calling the notepad.  Similarly, 
  680.     you may send a reset escape sequence after printing is complete
  681.     by defining a character variabled named RESET_STR.  You may also 
  682.     specify that a header be printed at the top of each page by 
  683.     declaring a public variable NOTEHEAD before calling the notepad.  
  684.     This one-line header will contain the filename (left-justified), 
  685.     the system date (centered), and the page number (right-justified).  
  686.     See below for examples of how to use these features.
  687.      
  688. b.  Using the Notepad in your Clipper applications:
  689.  
  690.     As with the other pop-ups, there are two ways to utilize the notepad.
  691.     The first and best is to use SET KEY to establish a hot-key so that 
  692.     the user can pop up the notepad from anywhere within the program.
  693.     The following lines added at the top of your program configures the F4
  694.     key to serve as the hot key for the notepad.
  695.  
  696.         EXTERNAL popnote          && define external symbol for linker
  697.         notekey = -3              && hot key will be function key F4
  698.         SET KEY notekey TO popnote
  699.  
  700.     The following example goes several steps further by establishing the
  701.     necessary variables to: (a) activate header printing (NOTEHEAD); 
  702.     (b) send a set-up string before printing (SETUP_STR); (c) send a 
  703.     reset sequence after printing is complete (RESET_STR); and (d) retain
  704.     the working filename, current directory, and wildcard upon exiting 
  705.     the notepad (NOTEFILE, CURR_DIR, WILDCARD).  The hypothetical user
  706.     will only need to edit files with the .TXT extesion, so WILDCARD is
  707.     set to '*.TXT'.  CHR(15) is a common escape sequence used to activate
  708.     compressed (reduced) print, and the CHR(18) sequence is commonly 
  709.     used to de-activate compressed print, so I have used these in my
  710.     example.
  711.     
  712.     EXTERNAL popnote                   && define external symbol for linker
  713.     PUBLIC notehead,notefile,curr_dir,wildcard,setup_str,reset_str
  714.     setup_str = chr(15)      
  715.     reset_str = chr(18)
  716.     wildcard = '*.TXT'
  717.     notekey = -3                       && hot key will be function key F4
  718.     SET KEY notekey TO popnote
  719.     
  720.     If you want to use a different hot key for the notepad, please refer
  721.     to your Clipper manual for a list of INKEY() values.
  722.  
  723.     The second method would be to call the notepad directly.  Please 
  724.     refer to the Calculator section above for a sample menu.  However,
  725.     I once again strongly recommend using SET KEY for maximum flexibility.
  726.  
  727.     Special thanks to Jim Barcus of Moundsville, WV for his advice on 
  728.     the notepad.
  729.  
  730.  
  731. 7.  MASTERMIND*****
  732.  
  733. a.  Description and Usage:
  734.  
  735.     Mastermind is a diversion when the user's brain needs a good workout!
  736.     It is based on the logic board game by Pressman Corporation.
  737.  
  738.     The computer selects four colored pegs and arranges them in a specific
  739.     sequence.  The player's objective is to determine both the color and
  740.     position of the four pegs by making educated guesses and analyzing the
  741.     clues that the computer dispenses after each guess.  These clues are:
  742.     one black marker for every peg that matches in both color and location;
  743.     and one white marker for every peg that is correct in color but not
  744.     location.  An average game will take from eight to ten guesses. To
  745.     choose a color, the user moves the highlight bar to the desired color
  746.     and presses Enter.  The user must choose colors from left to right.  If
  747.     the user wants to quit in the middle of a game, they may do so by
  748.     pressing Esc instead of selecting a color.  The program keeps track of
  749.     the guesses & clues on the right side of the screen so that the player
  750.     can refer back to them.
  751.  
  752. b.  Using Mastermind in your Clipper applications:
  753.  
  754.     As with the other applications, there are two ways to utilize
  755.     Mastermind. The first is to use SET KEY to establish a hot-key so that
  756.     the user can pop up Mastermind from anywhere within the program.  The
  757.     following lines added at the top of your program configures the F9 key
  758.     to serve as the hot key for Mastermind:
  759.  
  760.            EXTERNAL popmm        && define external symbol for linker
  761.            mmkey = -8            && hot key will be function key F9
  762.            SET KEY mmkey TO popmm
  763.  
  764.     If you want to use a different hot key for Mastermind, please refer to
  765.     your Clipper manual for a list of INKEY() values.
  766.  
  767.     The second method is to call Mastermind directly.  Refer to the
  768.     Calculator discussion for a sample menu.  However, SET KEY is highly
  769.     recommended.
  770.  
  771.  
  772. 8.  PUZZLE
  773.  
  774. a.  Description and Usage:
  775.  
  776.     Puzzle is the four by four square puzzle you had when you were a kid.
  777.     Fifteen of the squares are filled with the numbers 1-15, and it is up
  778.     to the player to arrange these in order like so:
  779.  
  780.                               ┌───┬───┬───┬───┐
  781.                               │ 1 │ 2 │ 3 │ 4 │
  782.                               ├───┼───┼───┼───┤
  783.                               │ 5 │ 6 │ 7 │ 8 │
  784.                               ├───┼───┼───┼───┤
  785.                               │ 9 │10 │11 │12 │
  786.                               ├───┼───┼───┼───┤
  787.                               │13 │14 │15 │   │
  788.                               └───┴───┴───┴───┘
  789.  
  790.     To move, the player types in the number of the piece they wish to move.
  791.     The program will not allow them to cheat.  Good luck - this can be
  792.     exasperatingly difficult!
  793.  
  794. b.  Using the Puzzle in your Clipper applications:
  795.  
  796.     As with the other applications, there are two ways to utilize the
  797.     puzzle. The first is to use SET KEY to establish a hot-key so that
  798.     the user can pop it up from anywhere within the program.  The
  799.     following lines added at the top of your program configures the F10 key
  800.     to serve as the hot key for the puzzle:
  801.  
  802.            EXTERNAL poppuz        && define external symbol for linker
  803.            puzkey = -9            && hot key will be F10
  804.            SET KEY puzkey TO poppuz
  805.  
  806.     If you want to use a different hot key for the puzzle, please refer to
  807.     your Clipper manual for a list of INKEY() values.
  808.  
  809.     The second method is to call the puzzle directly.  Refer to the
  810.     Calculator discussion for a sample menu.  However, SET KEY is highly
  811.     recommended.
  812.  
  813.  
  814. 9.  USING MULTIPLE POP-UP APPLICATIONS
  815.  
  816.     If you would like to integrate more than one of these pop-up
  817.     applications into your program, use the following code at the top of
  818.     your program:
  819.  
  820.        EXTERNAL help,popcalc,popphone,popdate,popmm,poppuz,popstop,popnote
  821.        notekey  = -3           && F4 = hot key for notepad
  822.        stopkey  = -4           && F5 = hot key for stopwatch
  823.        calckey  = -5           && F6 = hot key for calculator
  824.        phonekey = -6           && F7 = hot key for phone directory
  825.        phonedir = 'C:\PHONE'   && search directory for phone.dbf
  826.        datekey  = -7           && F8 = hot key for calendar
  827.        mmkey    = -8           && F9 = hot key for Mastermind
  828.        puzkey   = -9           && F10= hot key for puzzle
  829.        SET KEY notekey  TO popnote
  830.        SET KEY stopkey  TO popstop
  831.        SET KEY calckey  TO popcalc
  832.        SET KEY phonekey TO popphone
  833.        SET KEY datekey  TO popdate
  834.        SET KEY mmkey    TO popmm
  835.        SET KEY puzkey   TO poppuz
  836.  
  837.     However, if you incorporate all of the pop-up applications into your
  838.     program, you might never get any work done!!
  839.  
  840.  
  841. FUNCTIONS
  842.  
  843. 1.  YES_NO()
  844.  
  845.     This function displays a box with your message in it, and pauses
  846.     program execution until the user presses either 'Y' or 'N'.  It returns
  847.     a logical value: true if the user pressed 'Y', or false if the user
  848.     pressed 'N'.  The syntax is:
  849.  
  850.                        YES_NO(<message 1>[,<message 2>])
  851.  
  852.     where <message 1> and <message 2> are the messages you wish to have
  853.     displayed.  <Message 2> is optional.
  854.  
  855.     Sample use of YES_NO:
  856.  
  857.     kill_it = YES_NO('WARNING: Record will be deleted','Shall I continue')
  858.     IF kill_it
  859.        DELETE
  860.        SKIP -1
  861.     ENDIF
  862.  
  863.     Note that the function automatically adds "? (Y/N)" to your last
  864.     message.  For example, in the sample above, the following would be
  865.     displayed:
  866.  
  867.                        WARNING: Record will be deleted
  868.                            Shall I continue? (Y/N)
  869.  
  870.  
  871. 2.  ERR_MSG()
  872.  
  873.     This function displays a box with your error message in it, along with
  874.     several choice beeps, and pauses program execution until the user
  875.     presses any key.  It does not return a value.  The syntax is:
  876.  
  877.                               ERR_MSG(<message>)
  878.  
  879.     where <message> is the message you wish to display (not too
  880.     insulting, please!).
  881.  
  882.     Sample use of ERR_MSG:
  883.  
  884.     SEEK mVAR
  885.     IF .not. found()
  886.        ERR_MSG('That record was not found')
  887.     ENDIF
  888.  
  889.  
  890. 3.  CENTER()
  891.  
  892.     You will probably make frequent use of this function.  It centers
  893.     character strings, either on the screen or the printer, at the row you
  894.     specify. Syntax is:
  895.  
  896.     CENTER(<row>,<string>,[<length>])
  897.  
  898.     Required Parameters:
  899.  
  900.     <string> is the character string or expression to be centered.
  901.  
  902.     <row> is a numeric expression representing the row on which to
  903.     center the string.
  904.     
  905.     Optional Parameters:
  906.     
  907.     <length> is a numeric expression representing the length of a row
  908.     (default length is 80 for screen displays, but you may use values
  909.     of up to 255 when printing wide reports).
  910.  
  911.     Thanks to Jeanne Nerwinski of Durham, NC for the <length> parameter.
  912.  
  913.     Sample usage of CENTER:
  914.  
  915.     CENTER(0,'Change Order Data Input Screen')
  916.     CENTER(1,'WACKY WIDGETS MONTHLY PROFIT ANALYSIS',132)
  917.  
  918.  
  919. 4.  WAITON() and WAITOFF()
  920.  
  921.     This function is useful to keep the user of your application apprised
  922.     of time-consuming operations, such as printing a report, instead of
  923.     letting them stare at a blank screen and wonder what (if anything) is
  924.     going on.
  925.  
  926.     First, call WAITON(), which displays a box with your message in it.
  927.     The syntax is:
  928.  
  929.                              WAITON([<message>])
  930.  
  931.     where <message> is the message you wish to display.  Note that if you
  932.     do not pass a message, WAITON() will assume that you are about to print
  933.     a report and will display the message "Now printing... please wait".
  934.  
  935.     When the operation is complete, use WAITOFF() to refresh the screen.
  936.     The syntax is:
  937.  
  938.     WAITOFF()
  939.  
  940.     This will restore the screen to its original state.
  941.  
  942.     Sample usage of WAITON and WAITOFF:
  943.  
  944.          USE Sales
  945.          WAITON('Rebuilding index files... please wait')
  946.          INDEX ON lname TO Customer
  947.          INDEX ON date TO Saledate
  948.          INDEX ON inv_code TO Item
  949.          WAITOFF()
  950.  
  951.  
  952. 5.  EXBOX()
  953.  
  954.     Exploding boxes add enormous pizzaz to your color applications.  The
  955.     syntax is as follows:
  956.  
  957.        EXBOX(<top>,<left>,<bottom>,<right>,<box type>,<delay>,[<fill>])
  958.  
  959.     Required Parameters:
  960.  
  961.     <top> is an integer numeric representing the top row of the box.
  962.  
  963.     <left> is an integer numeric representing the leftmost column of the box.
  964.  
  965.     <bottom> is an integer numeric representing the bottom row of the box.
  966.  
  967.     <right> is an integer numeric representing the rightmost box column.
  968.  
  969.     <box type> is an integer numeric between 1 and 5, and represents the
  970.     type of box desired.  The choices are:
  971.  
  972.                  Box Type               Box String Used
  973.  
  974.                     1                      ╔═╗║╝═╚║
  975.                     2                      ┌─┐│┘─└│
  976.                     3                      ╒═╕│╛═╘│
  977.                     4                      ╓─╖║╜─╙║
  978.                     5                      █▀███▄██
  979.                     6                     (no border)
  980.  
  981.  
  982.     The box string forms the box in the same fashion as with Clipper's
  983.     "@...BOX" command.  The box is drawn using this string starting from
  984.     the left hand corner and proceeding clockwise.  If you need more
  985.     information on this, please refer to your Clipper manual.
  986.  
  987.     <delay> is an integer numeric between 1 and 100, and is used to delay
  988.     the 'explosion'.  The larger the delay, the longer the box drawing
  989.     operation will take.  I recommend using values between 1 and 10, but
  990.     you should experiment with this.
  991.  
  992.     Optional Parameter:
  993.  
  994.     <fill> is a character string to use as the fill character.  If the
  995.     length of the character string passed is greater than one, only
  996.     the leftmost character will be used.  If this parameter is not
  997.     specified, the fill character will be chr(32).
  998.  
  999.     Sample usage:
  1000.  
  1001.     EXBOX(11,28,13,51,2,5)
  1002.     @ 12,30 SAY 'Enter your ID:'
  1003.     @ 12,46 GET mID PICTURE 'XXXX'
  1004.     READ
  1005.  
  1006.     When using a monochrome monitor, an exploding box will not have any
  1007.     noticeable effect.
  1008.  
  1009.  
  1010. 6.  SHRBOX()
  1011.  
  1012.     What good are exploding boxes without shrinking boxes?  Now you can
  1013.     shrink that box you just exploded onto the screen back into
  1014.     nothingness.  Here's the syntax:
  1015.  
  1016.            SHRBOX(<top>,<left>,<bottom>,<right>,<delay>,[<color>])
  1017.  
  1018.     The first five parameters are identical to their namesakes in
  1019.     EXBOX().
  1020.  
  1021.     <color> is an optional character string parameter specifying the
  1022.     color you wish to use to blank out the previous box.  If not
  1023.     passed, the current color setting will be used.
  1024.  
  1025.     What SHRBOX() does is blank out the area marked by the speified
  1026.     coordinates from the outside in, exactly opposite the method used
  1027.     by EXBOX().
  1028.  
  1029.     Sample usage:
  1030.  
  1031.     (with the color parameter)
  1032.  
  1033.     SET COLOR TO +w/b
  1034.     EXBOX(11,17,13,62,2,5)
  1035.     @ 12,19 SAY 'This box will self-destruct in two seconds'
  1036.     INKEY(2)
  1037.     SHRBOX(11,17,13,62,2,'w/n')
  1038.  
  1039.     (without the color parameter)
  1040.  
  1041.     SET COLOR TO +w/b
  1042.     EXBOX(11,17,13,62,2,5)
  1043.     @ 12,19 SAY 'This box will self-destruct in two seconds'
  1044.     INKEY(2)
  1045.     SET COLOR TO w/n
  1046.     SHRBOX(11,17,13,62,2)
  1047.  
  1048.     As with the exploding box, a shrinking box will have no noticeable
  1049.     effect with monochrome monitors.
  1050.  
  1051.  
  1052. 7.  POPBOX()/DROPBOX()
  1053.  
  1054.     Surely you don't want to restrict yourself to exploding and
  1055.     shrinking boxes.  Toss in a pop-up or drop-down box here and there
  1056.     to keep the users on their toes.  Syntax:
  1057.     
  1058.            POPBOX / DROPBOX(<top>,<left>,<bottom>,<right>,<delay>)
  1059.  
  1060.     The first five parameters are identical to their namesakes in
  1061.     EXBOX() and SHRBOX().
  1062.  
  1063.     The pop-up box will be drawn from the bottom up, whereas the drop-
  1064.     down box will be drawn from the top down.
  1065.  
  1066.     Sample usage:
  1067.  
  1068.     POPBOX(5,5,23,55)
  1069.     @ 14,8 SAY 'This box rose like a phoenix from the ashes!'
  1070.     DROPBOX(1,60,11,79)
  1071.     @ 5,63 SAY 'This box fell'
  1072.     @ 6,63 SAY 'like pennies'
  1073.     @ 7,63 SAY 'from heaven!'
  1074.  
  1075.     (feel free to substitute cliches of your own choosing)
  1076.  
  1077.     Unlike the exploding and shrinking boxes, pop-up and drop-down
  1078.     boxes will be effective on monochrome monitors.
  1079.     
  1080.  
  1081. 8.  SETFILT()
  1082.  
  1083.     This function allows you to simulate SQL (structured query language)
  1084.     by establishing a query condition (or filter) for selectively printing
  1085.     or displaying records.  The syntax is hardly complex:
  1086.  
  1087.                                   SETFILT()
  1088.  
  1089.     SETFILT() returns a logical value.  The return value is true (.T.) if
  1090.     there are records found in the current database matching your query
  1091.     condition, false (.F.) if there are not.
  1092.  
  1093.     SETFILT() will display all of the field names of the current database
  1094.     file.  First, you move the highlight bar to the desired field and
  1095.     presses Enter to add it to the query condition.  You then select the
  1096.     desired operator (equal to, less than, greater than, less than or equal
  1097.     to, greater than or equal to, not equal to), and then the desired value
  1098.     for that field.  [For subsequent additions to the query condition, you
  1099.     will be asked to select a logical (Boolean) operator (AND/OR)]. Bear in
  1100.     mind that AND has precedence over OR when evaluating the query
  1101.     expression.  For example:
  1102.  
  1103.       DATE=CTOD('05/01/81') .and. COST=50.00 .or. ITEM='widget'
  1104.  
  1105.     will display all records with either (1) a date of 05/01/81 and a cost
  1106.     of 50.00, or (2) item 'widget'.  If you need more clarificationon
  1107.     logical (Boolean) operators, please refer to your Clipper manual for
  1108.     enlightenment.
  1109.  
  1110.     As you add items to the query condition, it will be updated on the
  1111.     screen so you can keep track of where you are.
  1112.  
  1113.     When you are finished establishing your query condition, press Esc to
  1114.     return to the calling program.
  1115.  
  1116.     Sample Usage:
  1117.  
  1118.     USE Sales
  1119.     IF setfilt()
  1120.        DISPLAY ALL
  1121.        SET FILTER TO
  1122.     ENDIF
  1123.     RETURN
  1124.  
  1125.  
  1126. 9.  BATCHREP()
  1127.  
  1128.     BATCHREP() allows the user to do global replaces within your program,
  1129.     in a similar fashion to the REPLACE command at the dBASE dot prompt.
  1130.     This function is invaluable for data-intensive applications.
  1131.  
  1132.     The syntax consists of the following line:
  1133.  
  1134.                                   BATCHREP()
  1135.  
  1136.     There is no return value.
  1137.  
  1138.     BATCHREP() will display all of the field names of the current database
  1139.     file.  First, you select the field yoiu wish to replace by moving the
  1140.     highlight bar to that field and pressing Enter.  You will then be
  1141.     prompted to enter the new value for that field.  Use dBASE III syntax;
  1142.     if you want to see examples, press Alt-H.  If the replacement field is
  1143.     character type, you will not be permitted to replace it with a value
  1144.     longer than the field's length.  If the replacement field is logical
  1145.     type, you must replace it with either .T. (True) or .F. (False),
  1146.     logically enough.
  1147.  
  1148.     After entering the new value, you then select the field or fields to
  1149.     define the replacement scope.  (If you want to unconditionally replace
  1150.     all records, hit Esc to begin the replacement.)  If you do select a
  1151.     field, you first select an operator (equal to, greater than, less than,
  1152.     etc.), and then enter a value for that field.  As you add to the
  1153.     replacement scope, it will be updated near the bottom of the screen.
  1154.     You can use as many fields as you wish; for each subsequent field,
  1155.     you will be asked to select a logical (Boolean) operator (AND/OR)].
  1156.     See SETFILT() above for an example of logical operators.
  1157.  
  1158.     When you are finished establishing the replacement scope, press Esc to
  1159.     begin the replacement.  If the field being REPLACEd is a key field in
  1160.     any open index, you will be prompted to that effect.  In this instance,
  1161.     the replacement will take slightly longer, because the index fields
  1162.     will have to be rebuilt after the replacement.  When the replacement is
  1163.     finished, the number of records replaced will appear in the center of
  1164.     the screen for reference.
  1165.  
  1166.     Sample Usage:
  1167.  
  1168.     USE Sales
  1169.     batchrep()
  1170.  
  1171.  
  1172. 10. MEMEDIT()
  1173.  
  1174.     This permits easy editing of memo fields.  The syntax is:
  1175.  
  1176.                  MEMEDIT(<mfield>,[<t>,<l>,<b>,<r>][,<msg>])
  1177.  
  1178.     Required Parameter:
  1179.  
  1180.     <mfield> is a character string representing the name of the memo field
  1181.     to be edited.
  1182.  
  1183.     Optional Parameters:
  1184.  
  1185.     <t>, <l>, <b>, <r> are all numeric expressions representing the
  1186.     box coordinates (top, left, bottom, right, respectively).  Default
  1187.     box coordinates are 5,10,19,69.
  1188.  
  1189.     <msg> is a character string to be centered at the top of your box.
  1190.  
  1191.     The active keys during MEMEDIT are exactly the same as those in the
  1192.     Clipper function MEMOEDIT().  Please refer to your manual for more
  1193.     specifics.
  1194.  
  1195.     Sample Usage:
  1196.  
  1197.     USE Letters
  1198.     MEMEDIT('text',10,20,15,59,'<< Edit Letter >>')
  1199.     RETURN
  1200.  
  1201.  
  1202. 11. MENUH()
  1203.  
  1204.     This function allows you to easily paint a horizontal Lotus-style
  1205.     light-bar menu on the screen.  The syntax is:
  1206.  
  1207.     MENUH(<row>,<col>,<spc>,<prompts>[,<messages>,<color>])
  1208.  
  1209.     Required Parameters:
  1210.  
  1211.     <row> is a numeric expression representing the row at which to display
  1212.     the light-bar menu.
  1213.  
  1214.     <col> is a numeric expression representing the starting column for the
  1215.     light-bar menu.
  1216.  
  1217.     <spc> is a numeric representing the desired spacing between menu
  1218.     entries.
  1219.  
  1220.     <prompts> is a character string containing all of the prompts for the
  1221.     menu.  These prompts must be separated by dollar signs.
  1222.  
  1223.     Optional Parameters:
  1224.  
  1225.     <messages> is a character string containing any desired messages
  1226.     corresponding to the prompts.  Like the prompts, the messages must
  1227.     be separated by dollar signs.  NOTE: You must SET MESSAGE in your
  1228.     program before calling MENUH(), or your messages will not be
  1229.     displayed!
  1230.  
  1231.     <color> is a character string used to set the menu color.  If this
  1232.     parameter is not passed, white on black will be used for the
  1233.     unselected options and inverse will be used for the light bar.
  1234.  
  1235.     Return Value:
  1236.     
  1237.     MENUH() returns a numeric value representing the selected menu option.
  1238.     For example, if the user pressed 'D' in the sample below the return
  1239.     value would be 1.
  1240.  
  1241.     Sample usage:
  1242.  
  1243.     sel=MENUH(23,5,4,'Data Entry$Reports$Previous Menu$','','+w/b,+w/n')
  1244.     DO CASE
  1245.        CASE sel = 1
  1246.           DO data
  1247.        CASE sel = 2
  1248.           DO reports
  1249.        OTHERWISE
  1250.           RETURN
  1251.     ENDCASE
  1252.  
  1253.  
  1254. 12. MENUV()
  1255.  
  1256.     This function will paint a vertical bounce-bar menu on the screen.
  1257.     First, you must define an array containing the desired menu options
  1258.     (and corresponding messages, if desired).  If you wish to have
  1259.     messages, you must separate the menu option from the message with a
  1260.     dollar sign.  Also, be sure to SET MESSAGE before calling MENUV().
  1261.  
  1262.     The syntax for this function is:
  1263.  
  1264.        MENUV(<array>[,<title>,<box type>,<box color>,<title color>])
  1265.  
  1266.     Required Parameter:
  1267.     
  1268.     <array> is a character string representing the name of the array that
  1269.     contains the menu options.
  1270.  
  1271.     Optional Parameters:
  1272.     
  1273.     <title> is a character string representing the menu title.
  1274.  
  1275.     <box type> is an integer between 1 and 12 corresponding to the
  1276.     type of box you wish to use.  Box types 1-4 are listed below:
  1277.  
  1278.                  Box Type               Box String Used
  1279.  
  1280.                     1                      ╔═╗║╝═╚║
  1281.                     2                      ┌─┐│┘─└│
  1282.                     3                      ╒═╕│╛═╘│
  1283.                     4                      ╓─╖║╜─╙║
  1284.                     5                      █▀███▄██
  1285.  
  1286.     Boxes 6-10 and 11-15 are identical to boxes 1-5, except that 6-10 will
  1287.     have an additional drop shadow (simulating a three-dimensional effect)
  1288.     and 11-15 will have two drop shadows for super-duper 3-D.
  1289.  
  1290.     <box color> is a character string containing the color to use for
  1291.     the box.  The default color is white on black for unselected
  1292.     options and inverse (black on white) for the bounce bar.
  1293.  
  1294.     <title color> is a character string containing the color to use
  1295.     for the menu title.  The default is white on black.
  1296.  
  1297.     Return Value:
  1298.     
  1299.     MENUV() returns a numeric value representing the selected menu option.
  1300.     For example, if the user pressed 'Q' in the sample below the return
  1301.     value would be 4.
  1302.  
  1303.     Sample usage:
  1304.  
  1305.     DECLARE mainmenu[4]
  1306.     mainmenu[1]='Maintain Data$Add and edit information'
  1307.     mainmenu[2]='Output Reports$Share your information'
  1308.     mainmenu[3]='Utilities$Select printer, reindex files'
  1309.     mainmenu[4]='Quit$Exit to DOS'
  1310.     sel=MENUV(mainmenu,'Main Menu',11,'+w/rb,+w/n','+w/b')
  1311.     DO CASE
  1312.        CASE sel = 1
  1313.           DO maintdata
  1314.        CASE sel = 2
  1315.           DO reports
  1316.        CASE sel = 3
  1317.           DO utility
  1318.        OTHERWISE
  1319.           RETURN
  1320.     ENDCASE
  1321.  
  1322.  
  1323. 13. NET_USE()
  1324.  
  1325.     This function and the two that follow are primarily for multi-user
  1326.     applications.  If you have any questions about the basics of 
  1327.     networking, I suggest that you refer to either the Clipper manual 
  1328.     or the Spring 1987 issue of "Nantucket News", which provides an 
  1329.     excellent tutorial.
  1330.     
  1331.     NET_USE() will open a specified database in either exclusive or 
  1332.     shared mode, along with up to eight corresponding index files.  
  1333.     The syntax is:
  1334.  
  1335.     NET_USE(<filename>,<excl_use> [,<index1>,<index2>,...<index8>]
  1336.     
  1337.     Required Parameters:
  1338.    
  1339.     <filename> is a character string representing the name of the
  1340.     database file to be opened.
  1341.     
  1342.     <excl_use> is a logical expression representing the desired mode:
  1343.     True (.T.) for exclusive, False (.F.) for shared.
  1344.     
  1345.     Optional Parameters:
  1346.     
  1347.     <index1>...<index8> are character strings representing the names
  1348.     of the index files to be opened.
  1349.     
  1350.     Return Value:
  1351.     
  1352.     NET_USE() returns a logical value: True (.T.) if the file was
  1353.     opened successfully, or False (.F.) if it was not.
  1354.     
  1355.     If NET_USE() is unable to open the file, the user will be asked if
  1356.     they wish to wait for it to become available.  If not, the return
  1357.     value will be False.  If they do decide to wait, they will be
  1358.     entertained by an intriguing screen display.  They may abort the
  1359.     wait at any time by pressing Esc (which will then cause the
  1360.     function to return False).
  1361.     
  1362.     This function also provides aural feedback to the user, so that if
  1363.     they want to wait for the file, they do not necessarily have to
  1364.     remain glued to the screen.  When the file becomes available, the
  1365.     Charge theme will be played, which is sure to get a Pavlovian
  1366.     response from your users!
  1367.     
  1368.     You will note the absence of explicit selection of work areas.
  1369.     NET_USE() takes advantage of the Clipper "SELECT 0" command to
  1370.     automatically select the next available work area.
  1371.     
  1372.     WARNING: You must SET EXCLUSIVE OFF prior to calling this
  1373.     function.  If you do not, NET_USE() will attempt to open all files
  1374.     exclusively, which will give you a terrible headache.
  1375.     
  1376.     Sample Usage:
  1377.     
  1378.     IF ! NET_USE('customer',.f.,'cust1','cust2')
  1379.        RETURN
  1380.     ENDIF
  1381.     ** code to maintain customer file
  1382.     |
  1383.     |
  1384.     IF ! NET_USE('customer',.t.,'cust1')
  1385.        RETURN
  1386.     ENDIF
  1387.     ** code to print customer reports
  1388.     
  1389.     
  1390. 14. REC_LOCK()/FILELOCK()
  1391.  
  1392.     These two functions are crucial in any multi-user system.  
  1393.     Obviously enough, REC_LOCK() is used to lock records, while
  1394.     FILELOCK() locks files.  The syntax is simple:
  1395.     
  1396.     REC_LOCK() / FILELOCK()
  1397.     
  1398.     Required Parameters:
  1399.     
  1400.     None.
  1401.     
  1402.     Return Value:
  1403.     
  1404.     Both functions return logical values: True (.T.) if the lock was
  1405.     successful, or False (.F.) if unsuccessful.
  1406.     
  1407.     If the locks are initially unsuccessful, the user will be given
  1408.     the option to wait for availability in the same fashion as with
  1409.     NET_USE().  Likewise, a dazzling screen will keep them amused
  1410.     while they wait, and the Charge theme will be played when the lock
  1411.     is finally successful.
  1412.           
  1413.     Sample Usage:
  1414.     
  1415.     IF REC_LOCK()
  1416.        REPLACE name WITH mname, address WITH maddress
  1417.     ENDIF
  1418.  
  1419.     IF FILELOCK()
  1420.        DO reports
  1421.     ENDIF
  1422.     
  1423.  
  1424. 15. ADD_REC()
  1425.  
  1426.     This function is for APPENDing BLANK records to a database in a
  1427.     multi-user system.  The syntax is:
  1428.     
  1429.     ADD_REC([<wait time>])
  1430.     
  1431.     Optional parameter <wait time> is a numeric expression
  1432.     representing the number of seconds to wait for the APPEND BLANK to
  1433.     be successful.  If this parameter is not passed, the function will
  1434.     loop until either the APPEND BLANK is successful or the user
  1435.     presses Esc.
  1436.  
  1437.     Return Value:
  1438.     
  1439.     ADD_REC() returns a logical value: True (.T.) if the APPEND BLANK
  1440.     is successful, or False (.F.) if it did not succeed within the
  1441.     specified time.  Please note that it is highly unlikely that this
  1442.     function will ever return False, except in the rare event that two
  1443.     users have attempted to APPEND BLANK to the same database at
  1444.     precisely the same time.
  1445.     
  1446.  
  1447. 16. HELPBROW()
  1448.  
  1449.     Most of us have written at least one program that utilizes small
  1450.     "look-up" databases containing codes relating to more verbose
  1451.     descriptions.  Typical data entry for such fields in the primary
  1452.     database would involve using a VALID() clause, in which you seek 
  1453.     the value against the look-up database and return a value of True
  1454.     if it is found.  This arrangement is quite workable as is, but 
  1455.     what if the user enters an invalid entry?  Wouldn't it be slick to
  1456.     pop up a scrolling list of all valid entries, along with the 
  1457.     descriptions they correspond to?  Then the user can simply point-
  1458.     and-shoot.  Plus, if the field in question is character-type, 
  1459.     why not give the user a quick search facility to zoom in on the
  1460.     desired value?
  1461.     
  1462.     Enter HELPBROW().  This function is best suited for validating
  1463.     data as described above.  Although this function requires more 
  1464.     programming than most of the other Grumpfish functions, it will
  1465.     be worth the effort.  The syntax is as follows:
  1466.     
  1467.     HELPBROW(<search area>, <return field>, <heading 1>, [<description>,
  1468.     <heading 2>, <box color>, <row coord>, <col coord>])
  1469.     
  1470.     Required Parameters:
  1471.  
  1472.     <search area> is a character string representing the work area to
  1473.     use for the SEEK.  Obviously, this database should be opened prior
  1474.     to calling HELPBROW(), else the heartbreaking "Type Mismatch" will
  1475.     ruin someone's day.
  1476.  
  1477.     <return field> is a character string representing the name of the
  1478.     field to be returned from the search area.  DO NOT include the 
  1479.     alias when specifying this parameter; for example, use 'CODE'
  1480.     rather than 'TYPES->CODE'.
  1481.     
  1482.     <heading 1> is a character string representing the heading to be 
  1483.     used for the first column of the browse window.
  1484.     
  1485.     Optional parameters:
  1486.     
  1487.     <description> is a character string representing the name of a 
  1488.     secondary field to be displayed in the browse window.  As with
  1489.     the return field parameter, do not include the alias.
  1490.     
  1491.     <heading 2> is a character string to be used for the heading of
  1492.     the second column of the browse window.  
  1493.     
  1494.     <box color> is a character string representing the color with 
  1495.     which to draw the browse window.  The default is a pleasant 
  1496.     white on blue.
  1497.     
  1498.     If you wish to display the secondary field on the screen after
  1499.     validation, use parameters <row coord> and <col coord> as the
  1500.     row and column coordinates, respectively, at which to display it.
  1501.     
  1502.     Return Value:
  1503.     
  1504.     HELPBROW() returns True (.T.) if the variable in the READ is found
  1505.     in the look-up database or if the user selects one of the values
  1506.     shown in the browse window.  It returns False (.F.) if the user 
  1507.     does not enter a value that is found in the look-up database.
  1508.     
  1509.     Sample Usage:
  1510.     
  1511.     Let's suppose that you want to keep track of the gender of everyone
  1512.     in your 250,000 record rolodex database (you must be very popular).
  1513.     You thoughtfully design the field GENDER as character type with a
  1514.     length of one to save space, and create a small look-up database 
  1515.     entitled GENDERS.dbf, which contains the following four records:
  1516.     
  1517.                Type        Description
  1518.                 M          MALE
  1519.                 F          FEMALE
  1520.                 N          NEUTER
  1521.                 O          OTHER
  1522.                                         
  1523.     You want to display the full gender description on the data entry
  1524.     screen right next to the field GENDER.  This is how you could 
  1525.     write the call to HELPBROW():
  1526.     
  1527.     @ 16,10 GET mGENDER PICTURE '!' VALID HELPBROW('genders', 'type', ;
  1528.                 'TYPE', 'description', 'DESCRIPTION', '', 16, 13)
  1529.         
  1530.     Now, if your user enters 'E' (for Eunuch??), (s)he will be
  1531.     confronted with a window showing the four valid entries and will
  1532.     be prompted to select one.  They will not be able to proceed until
  1533.     they do so.  Once they select a value, the verbose description
  1534.     will be displayed at row 16, column 13 for reference.
  1535.  
  1536.     Quick-Search: if the index key in the search area is of character
  1537.     type, quick-search will automatically be activated.  This allows
  1538.     the user to jump quickly to values by typing in the first few
  1539.     letters of the desired value.  For example, searching for the 
  1540.     code 'RPG' could prove quite tedious in a 100-record database, but
  1541.     with quick-search the user need only type in the letters 'R' and
  1542.     'P' to jump directly to it.  Your users will love it!
  1543.     
  1544.  
  1545. 17. PRINTOK()
  1546.  
  1547.     How many times have you or your users had problems with printers
  1548.     not being ready?  Use this function and you might never have to
  1549.     deal with "Printer Not Ready.... Retry (Y/N)?" again.  Syntax:
  1550.  
  1551.     PRINTOK()
  1552.  
  1553.     It returns a logical value.  If the printer is ready, it will
  1554.     return True (.T.) and SET the DEVICE TO PRINT.  If the printer is
  1555.     not ready, it will return False (.F.).
  1556.  
  1557.     Sample usage:
  1558.  
  1559.     IF PRINTOK()
  1560.        DO report
  1561.        SET DEVICE TO SCREEN
  1562.     ENDIF
  1563.  
  1564.  
  1565. 18. DATEST()
  1566.  
  1567.     If you want to print an empty date field or expression in a report
  1568.     without printing the slashes ('  /  /  '), use DATEST() instead of
  1569.     DTOC() like so:
  1570.  
  1571.     DATEST(<date>)
  1572.  
  1573.     where <date> is the date field or expression you wish to print.
  1574.  
  1575.  
  1576. 19. ISSTATE()
  1577.  
  1578.     This function is useful in applications where the user must input a
  1579.     two-character state abbreviation.  ISSTATE() checks to ensure that a
  1580.     valid abbreviation has been entered.  The syntax is:
  1581.  
  1582.     ISSTATE(<memvar>)
  1583.  
  1584.     where <memvar> is a character expression to be tested.
  1585.  
  1586.     ISSTATE() returns a logical value: True (.T.) if the expression is a
  1587.     valid state abbreviation, or False (.F.) if it is not.
  1588.  
  1589.     Sample Usage:
  1590.  
  1591.     mSTATE = space(2)
  1592.     @ 10,10 get mSTATE valid isstate(mSTATE)
  1593.  
  1594.  
  1595. 20. SPREAD()
  1596.  
  1597.     This function lets you display a character string on the screen
  1598.     from the middle out.  If this does not make sense, try it for
  1599.     yourself.  It is simple, yet slick.  The syntax is as follows:
  1600.  
  1601.                    SPREAD(<string>,<row>[,<delay>,<column>])
  1602.  
  1603.     <string> is the character string to display.
  1604.  
  1605.     <row> is the row at which to display it.
  1606.  
  1607.     Optional parameter <delay> is a numeric integer to delay the
  1608.     effect.  The default delay setting is 8.  Experiment with this
  1609.     until you find one that you like.
  1610.  
  1611.     Optional parameter <column> is a numeric integer specifying the
  1612.     column at which to spread the string out from (the default is 40).
  1613.  
  1614.     Sample usage:
  1615.  
  1616.     SPREAD("This effect will get the user's attention!",12)
  1617.     SPREAD("This line will be drawn very slowly",14,50)
  1618.  
  1619.  
  1620. 21. TTY()
  1621.  
  1622.     This function displays a character string across the screen in a
  1623.     continuously scrolling "teletype" manner until the user presses 
  1624.     any key.  The syntax is as follows:
  1625.     
  1626.                         TTY(<row>, <message>, <delay>)
  1627.             
  1628.     <row> is a numeric expression representing the row at which to
  1629.     display the message.
  1630.     
  1631.     <message> is the character string to be displayed.
  1632.     
  1633.     <delay> is a numeric expression representing the delay factor to
  1634.     be introduced into the scrolling process.  Values between 10 and 
  1635.     100 are recommended, although you should experiment to determine 
  1636.     what works best on your particular computer.
  1637.     
  1638.     There is no return value.  The message will scroll across the
  1639.     screen until the user presses a key.
  1640.     
  1641.     Sample Usage:
  1642.     
  1643.     TTY(12, 'Press any key to return to the Main Menu', 75)
  1644.     
  1645.     Thanks again to Jeanne Nerwinski of Durham, NC for suggesting TTY().
  1646.  
  1647.  
  1648. 22. PASS_CHK()
  1649.  
  1650.     This is a generic routine to be used whenever the user must enter a
  1651.     password to continue.  The syntax is as follows:
  1652.  
  1653.     PASS_CHK(<password>, [<row>])
  1654.  
  1655.     where <password> is a character expression and <row> is an optional
  1656.     parameter indicating the row number at which you want the "Enter
  1657.     password..." message to appear.
  1658.  
  1659.     PASS_CHK() compares the user's entry against the password you
  1660.     passed to it.  The function is case-insensitive.
  1661.  
  1662.     PASS_CHK() returns a logical value: True (.T.) if the user
  1663.     enters the correct password, or False (.F.) if they do not.
  1664.  
  1665.     Sample Usage:
  1666.  
  1667.     IF pass_chk(chr(77)+chr(79)+chr(79)+chr(76)+chr(65))  && MOOLA
  1668.        DO payroll
  1669.     ENDIF
  1670.  
  1671.  
  1672. 23. RAND()
  1673.  
  1674.     Here is a random number generator so that you can work on that pop-up
  1675.     poker game you've been dreaming of!  It is driven by the system clock,
  1676.     so there is no need for you to initialize a 'seed'.  Syntax is:
  1677.  
  1678.     RAND(<range>)
  1679.  
  1680.     where <range> is an integer numeric expression.
  1681.  
  1682.     RAND() will return a random integer between zero and <range>-1.
  1683.  
  1684.     Sample Usage:                       Output:
  1685.  
  1686.     ? RAND(100)                           75
  1687.     ? RAND(50)                            22
  1688.     ? RAND(10)                             7
  1689.  
  1690.     By the way, if anyone out there does crave a pop-up poker game and 
  1691.     does not want to invest the time to program one, I know of one 
  1692.     demented individual who might be persuaded to tackle such a project.
  1693.  
  1694. 24. TIMEWORD()
  1695.  
  1696.     This function may seem trivial, but believe it or not, you might
  1697.     find use for it someday.  It simply returns a word describing the
  1698.     time of day (based on the system clock).  Syntax:
  1699.  
  1700.     TIMEWORD()
  1701.  
  1702.     There are no parameters.
  1703.  
  1704.     The return value is a character string which relates to the time as
  1705.     follows:
  1706.  
  1707.     12:00 am - 11:59 am    "Morning"
  1708.     12:00 pm -  5:59 pm    "Afternoon"
  1709.      6:00 pm - 11:59 pm    "Evening"
  1710.  
  1711.     I use this in several of my multi-user systems in the following
  1712.     manner: first, an environmental variable with the user's name is
  1713.     defined in the network login script.  Then I grab the user's name
  1714.     with the Clipper function GETE() and use TIMEWORD() to give them a
  1715.     personal and time-specific greeting when they enter my program. Not
  1716.     exactly a cure for cancer, but it is a nice touch.
  1717.  
  1718.     Sample Usage:
  1719.  
  1720.     @ 12,20 say 'Good '+TIMEWORD()+', '+user_name
  1721.  
  1722.  
  1723. 25. GL_VER()
  1724.  
  1725.     This function simply returns the version number of the Grumpfish
  1726.     Library that you are using.
  1727.  
  1728.     Sample Usage:
  1729.     
  1730.     ? GL_VER()
  1731.     
  1732.  
  1733. THE SINGING P.C.
  1734.  
  1735.     A number of musical themes are available to you if you dare to use
  1736.     them.  They are listed below, followed by the code syntax to call them.
  1737.  
  1738.     1.  "Beat It" by Michael Jackson (intro) - DO BEATIT
  1739.     2.  "Born to Run" by Bruce Springsteen (one verse) - DO BORN2RUN
  1740.     3.  "Charge!" as heard at finer sporting events everywhere - DO CHARGE
  1741.     4.  "Mexican Hat Dance", popular at many hockey rinks - DO HATDANCE
  1742.     5.  "The Girl from Ipanema" - DO IPANEMA
  1743.     6.  "Theme from Final Jeopardy" - DO JEOPARDY
  1744.     7.  "Deck The Halls" - DO DECKHALL
  1745.     8.  "Jingle Bells" - DO JINGLE
  1746.     9.  "Rudolph The Red-Nosed Reindeer" - DO RUDOLPH
  1747.    
  1748.     If you have any musical requests, please let me know!
  1749.  
  1750.  
  1751. FUTURE IMPROVEMENTS
  1752.  
  1753. If you have any ideas at all (or musical requests), send them my way!!
  1754.  
  1755.                              Greg Lief
  1756.                              P. O. Box 17761
  1757.                              Salem, Oregon 97305
  1758.  
  1759. TRADEMARK ACKNOWLEDGEMENTS
  1760.  
  1761. CLIPPER is a registered trademark of Nantucket Corporation.
  1762.  
  1763. PLINK86 is a registered trademark of Phoenix Technologies.
  1764.  
  1765. DOS is a registered trademark of Microsoft Corporation.
  1766.  
  1767. TLINK (Turbo Link) is a registered trademark of Borland International.
  1768.  
  1769. MASTERMIND is a registered trademark of Pressman Corporation.
  1770.  
  1771. LOTUS is a registered trademark of Lotus Development Corporation.
  1772.  
  1773.  
  1774.  
  1775. REVISION HISTORY
  1776.  
  1777.     1.0 - July 1988 (initial release)
  1778.  
  1779.     1.1 - August 1988 - corrected discrepancy between documentation and
  1780.     source code regarding hot key implementation for pop-ups.  Added
  1781.     SETFILT(), BATCHREP(), ISSTATE(), RAND(), and <length> parameter for
  1782.     CENTER().
  1783.  
  1784.     1.2 - September 1988 - Added POPSTOP, paste function for POPCALC,
  1785.     and PASS_CHK().  Added solid border box option to EXBOX().  Updated
  1786.     most functions to properly set colors dependent upon type of
  1787.     monitor (color vs. monochrome).  Corrected MEMED() so that menu
  1788.     title is centered properly between left and right columns.
  1789.  
  1790.     1.25 - October 1988 - Added SHRBOX(), SPREAD(), TIMEWORD(),
  1791.     PRINTOK(),  and fill character option for EXBOX().  Cleaned up
  1792.     documentation and added demo program with supporting databases to
  1793.     distribution disk. 
  1794.  
  1795.     1.3 - November 1988 - Added multi-user functions (NET_USE, ADD_REC,
  1796.     FILELOCK, REC_LOCK).  Added POPBOX(), DROPBOX(), and GL_VER().
  1797.     Added IPANEMA to the Singing P.C.'s repertoire, and made it
  1798.     possible to escape from any of the songs as they play.
  1799.  
  1800.     1.31 - November 1988 - Fixed persistent bug in POPCALC involving
  1801.     use and pasting of non-integer numbers, and added TTY().
  1802.     
  1803.     1.4 - December 1988 - Added POPNOTE and greatly improved the level
  1804.     of customization available with the pop-up help screens.  Added 
  1805.     interactive help screen function (HELPBROW).  Also reduced overhead
  1806.     requirements for BATCHREP().  Made various minor aesthetic changes
  1807.     in the pop-up applications.  Added three Christmas songs to the
  1808.     Singing P.C.'s expanding repertoire.
  1809.     
  1810.     1.5 - expected mid-January 1989 - Will add reporting (and perhaps 
  1811.     label) capability to phone directory.  Will add appointment minder
  1812.     to calendar.  Will probably make help screen development interface
  1813.     more 'user-friendly'.  May add 'paper tape' function to calculator 
  1814.     if there is enough demand for it.  May cure cancer if time permits.